یاد بگیرید چگونه سیستمهای OLAP و انبار داده قدرتمندی را با استفاده از پایتون طراحی و بسازید. این راهنما همه چیز را پوشش میدهد.
انبار داده پایتون: راهنمای جامع برای طراحی سیستم OLAP
در دنیای امروزی مبتنی بر داده، توانایی تجزیه و تحلیل سریع حجم وسیعی از اطلاعات نه تنها یک مزیت رقابتی است، بلکه یک ضرورت است. کسبوکارها در سراسر جهان برای درک روند بازار، بهینهسازی عملیات و اتخاذ تصمیمات استراتژیک به تجزیه و تحلیلهای قوی متکی هستند. در قلب این قابلیتهای تحلیلی دو مفهوم اساسی نهفته است: انبار داده (DWH) و سیستمهای پردازش تحلیلی برخط (OLAP).
به طور سنتی، ساخت این سیستمها به نرمافزارهای تخصصی، اغلب اختصاصی و گرانقیمت نیاز داشت. با این حال، ظهور فناوریهای متنباز مهندسی دادهها را دموکراتیزه کرده است. پایتون، یک زبان همه کاره و قدرتمند با یک اکوسیستم غنی که آن را به انتخابی استثنایی برای ساخت راهحلهای داده پایان به پایان تبدیل میکند، این روند را رهبری میکند. این راهنما یک راهنمای جامع برای طراحی و پیادهسازی انبار داده و سیستمهای OLAP با استفاده از پشته پایتون ارائه میدهد که برای مخاطبان جهانی مهندسین، معماران و توسعهدهندگان دادهها طراحی شده است.
بخش 1: سنگ بنای هوش تجاری - DWH و OLAP
قبل از پرداختن به کد پایتون، درک اصول معماری بسیار مهم است. یک اشتباه رایج این است که تجزیه و تحلیل را مستقیماً بر روی پایگاههای داده عملیاتی انجام دهیم، که میتواند منجر به عملکرد ضعیف و بینشهای نادرست شود. این مشکلی است که انبار دادهها و OLAP برای حل آن طراحی شدهاند.
انبار داده (DWH) چیست؟
انبار داده یک مخزن متمرکز است که دادههای یکپارچه را از یک یا چند منبع ناهمگون ذخیره میکند. هدف اصلی آن پشتیبانی از فعالیتهای هوش تجاری (BI)، بهویژه تجزیه و تحلیل و گزارشدهی است. آن را به عنوان تنها منبع حقیقت برای دادههای تاریخی یک سازمان در نظر بگیرید.
این با یک پایگاه داده پردازش تراکنشهای آنلاین (OLTP) که برنامههای روزمره (به عنوان مثال، سیستم تسویه حساب تجارت الکترونیک یا دفتر کل تراکنشهای بانک) را اجرا میکند، تفاوت چشمگیری دارد. در اینجا یک مقایسه سریع آورده شده است:
- بار کاری: سیستمهای OLTP تعداد زیادی تراکنش کوچک و سریع (خواندن، درج، بهروزرسانی) را مدیریت میکنند. DWH ها برای تعداد کمتری از پرسوجوهای پیچیده و طولانی که میلیونها رکورد را اسکن میکنند (خواندن سنگین) بهینه شدهاند.
- ساختار داده: پایگاههای داده OLTP برای اطمینان از یکپارچگی دادهها و جلوگیری از افزونگی، بسیار نرمال شدهاند. DWH ها اغلب برای سادهسازی و تسریع پرسوجوهای تحلیلی، غیر نرمال میشوند.
- هدف: OLTP برای اداره کسبوکار است. DWH برای تجزیه و تحلیل کسبوکار است.
یک DWH خوب طراحی شده با چهار ویژگی کلیدی مشخص میشود که اغلب به پیشگام بیل اینمون نسبت داده میشود:
- موضوعگرا: دادهها حول موضوعات اصلی کسبوکار، مانند «مشتری»، «محصول» یا «فروش» سازماندهی میشوند، نه فرآیندهای برنامه.
- یکپارچه: دادهها از منابع مختلف جمعآوری شده و در یک قالب سازگار یکپارچه میشوند. به عنوان مثال، «USA»، «ایالات متحده» و «U.S.» ممکن است همگی به یک ورودی واحد «ایالات متحده» استاندارد شوند.
- متغیر زمانی: دادهها در انبار، اطلاعات را در یک بازه زمانی طولانی (به عنوان مثال، 5-10 سال) نشان میدهند و امکان تجزیه و تحلیل تاریخی و شناسایی روندها را فراهم میکنند.
- غیر فرار: هنگامی که دادهها در انبار بارگذاری میشوند، به ندرت یا هرگز بهروزرسانی یا حذف نمیشوند. این به یک سابقه دائمی از رویدادهای تاریخی تبدیل میشود.
OLAP (پردازش تحلیلی برخط) چیست؟
اگر DWH کتابخانه دادههای تاریخی است، OLAP موتور جستجو و ابزار تحلیلی قدرتمندی است که به شما امکان میدهد آن را کاوش کنید. OLAP یک دسته از فناوریهای نرمافزاری است که به کاربران امکان میدهد به سرعت اطلاعاتی را که در نماهای چند بعدی خلاصه شدهاند، که به عنوان مکعبهای OLAP شناخته میشوند، تجزیه و تحلیل کنند.
مکعب OLAP قلب مفهومی OLAP است. لزوماً یک ساختار داده فیزیکی نیست، بلکه راهی برای مدلسازی و تجسم دادهها است. یک مکعب شامل موارد زیر است:
- اندازهگیریها: اینها نقاط دادههای کمی و عددی هستند که میخواهید تجزیه و تحلیل کنید، مانند «درآمد»، «مقدار فروش» یا «سود».
- ابعاد: اینها ویژگیهای طبقهبندی هستند که اندازهگیریها را توصیف میکنند و زمینه را فراهم میکنند. ابعاد رایج عبارتند از «زمان» (سال، سه ماهه، ماه)، «جغرافیا» (کشور، منطقه، شهر) و «محصول» (دسته، نام تجاری، SKU).
یک مکعب از دادههای فروش را تصور کنید. میتوانید به کل درآمد (اندازهگیری) در ابعاد مختلف نگاه کنید. با OLAP، میتوانید عملیات قدرتمندی را با این سرعت باورنکردنی روی این مکعب انجام دهید:
- برش: کاهش ابعاد مکعب با انتخاب یک مقدار واحد برای یک بعد. مثال: مشاهده دادههای فروش فقط برای «سه ماهه 4 سال 2023».
- حذف: انتخاب یک زیر مکعب با تعیین محدودهای از مقادیر برای ابعاد متعدد. مثال: مشاهده فروش برای «الکترونیک» و «پوشاک» (بعد محصول) در «اروپا» و «آسیا» (بعد جغرافیا).
- افزایش / کاهش عمق: پیمایش از طریق سطوح جزئیات در یک بعد. افزایش عمق از خلاصههای سطح بالاتر به جزئیات سطح پایینتر (به عنوان مثال، از «سال» به «سه ماهه» تا «ماه») حرکت میکند. کاهش عمق (یا بالا بردن) برعکس است.
- محوری: چرخاندن محورهای مکعب برای به دست آوردن نمای جدیدی از دادهها. مثال: تعویض محورهای «محصول» و «جغرافیا» برای مشاهده اینکه کدام مناطق کدام محصولات را خریداری میکنند، به جای اینکه کدام محصولات در کدام مناطق فروخته میشوند.
انواع سیستمهای OLAP
سه مدل معماری اصلی برای سیستمهای OLAP وجود دارد:
- MOLAP (OLAP چند بعدی): این مدل مکعب «کلاسیک» است. دادهها از DWH استخراج شده و به یک پایگاه داده اختصاصی و چند بعدی از پیش جمعآوری میشوند. مزایا: عملکرد پرسوجوی بسیار سریع، زیرا همه پاسخها از قبل محاسبه شدهاند. معایب: میتواند منجر به «انفجار دادهها» شود، زیرا تعداد سلولهای از پیش جمعآوری شده میتواند بسیار زیاد شود و اگر نیاز به پرسیدن سؤالی داشته باشید که پیشبینی نشده است، میتواند انعطافپذیری کمتری داشته باشد.
- ROLAP (OLAP رابطهای): این مدل دادهها را در یک پایگاه داده رابطهای (معمولاً خود DWH) نگه میدارد و از یک لایه ابرداده پیچیده برای ترجمه پرسوجوهای OLAP به SQL استاندارد استفاده میکند. مزایا: مقیاسپذیری بالا، زیرا از قدرت پایگاههای داده رابطهای مدرن استفاده میکند و میتواند دادههای دقیقتر و بیدرنگ را پرسوجو کند. معایب: عملکرد پرسوجو میتواند کندتر از MOLAP باشد، زیرا تجمیعها در حال پرواز انجام میشوند.
- HOLAP (OLAP ترکیبی): این رویکرد تلاش میکند تا بهترینهای هر دو جهان را ترکیب کند. دادههای تجمعی سطح بالا را در یک مکعب به سبک MOLAP برای سرعت ذخیره میکند و دادههای دقیق را در پایگاه داده رابطهای ROLAP برای تجزیه و تحلیل کاهش عمق حفظ میکند.
برای پشتههای دادههای مدرن ساخته شده با پایتون، خطوط محو شدهاند. با ظهور پایگاههای داده ستونی با سرعت باورنکردنی، مدل ROLAP غالب و بسیار مؤثر شده است، که اغلب عملکردی را ارائه میدهد که با سیستمهای MOLAP سنتی رقابت میکند، بدون اینکه از این نظر سختگیر باشد.
بخش 2: اکوسیستم پایتون برای انبار داده
چرا پایتون را برای وظیفهای انتخاب میکنید که بهطور سنتی تحت سلطه پلتفرمهای BI سازمانی است؟ پاسخ در انعطافپذیری، اکوسیستم قدرتمند و توانایی آن در یکپارچهسازی کل چرخه عمر دادهها نهفته است.
چرا پایتون؟
- یک زبان یکپارچه: میتوانید از پایتون برای استخراج دادهها (ETL)، تبدیل، بارگیری، هماهنگی، تجزیه و تحلیل، یادگیری ماشین و توسعه API استفاده کنید. این امر پیچیدگی و نیاز به تغییر زمینه بین زبانها و ابزارهای مختلف را کاهش میدهد.
- اکوسیستم کتابخانه وسیع: پایتون دارای کتابخانههای بالغ و آزمایش شده برای هر مرحله از فرآیند است، از دستکاری دادهها (Pandas، Dask) تا تعامل با پایگاه داده (SQLAlchemy) و مدیریت گردش کار (Airflow، Prefect).
- فروشنده-ناشناس: پایتون متنباز است و به همه چیز متصل میشود. این که دادههای شما در یک پایگاه داده PostgreSQL، یک انبار Snowflake، یک دریاچه داده S3 یا یک صفحه Google قرار داشته باشد، یک کتابخانه پایتون برای دسترسی به آن وجود دارد.
- مقیاسپذیری: راهحلهای پایتون میتوانند از یک اسکریپت ساده که روی لپتاپ اجرا میشود تا یک سیستم توزیعشده که پتابایتها داده را روی یک خوشه ابری پردازش میکند، با استفاده از ابزارهایی مانند Dask یا Spark (از طریق PySpark) مقیاسبندی شوند.
کتابخانههای اصلی پایتون برای پشته انبار داده
یک راهحل انبار داده مبتنی بر پایتون معمولی یک محصول واحد نیست، بلکه مجموعهای از کتابخانههای قدرتمند است. در اینجا موارد ضروری وجود دارد:
برای ETL/ELT (Extract, Transform, Load)
- Pandas: استاندارد واقعی برای دستکاری دادهها در حافظه در پایتون. مناسب برای مدیریت مجموعهدادههای کوچک تا متوسط (حداکثر چند گیگابایت). شی DataFrame آن برای پاکسازی، تبدیل و تجزیه و تحلیل دادهها شهودی و قدرتمند است.
- Dask: یک کتابخانه محاسباتی موازی که تجزیه و تحلیل پایتون شما را مقیاسبندی میکند. Dask یک شی DataFrame موازی ارائه میدهد که از API Pandas تقلید میکند، اما میتواند روی مجموعهدادههایی که بزرگتر از حافظه هستند، با تقسیم آنها به تکهها و پردازش موازی آنها در سراسر چندین هسته یا دستگاه، کار کند.
- SQLAlchemy: ابزارک SQL برتر و Mapper رابطهای شی (ORM) برای پایتون. این یک API سازگار و سطح بالا برای اتصال به تقریباً هر پایگاه داده SQL، از SQLite تا انبارهای درجه سازمانی مانند BigQuery یا Redshift ارائه میدهد.
- هماهنگکنندههای گردش کار (Airflow، Prefect، Dagster): یک انبار داده بر روی یک اسکریپت واحد ساخته نمیشود. این مجموعهای از وظایف وابسته است (استخراج از A، تبدیل B، بارگیری به C، بررسی D). هماهنگکنندهها به شما امکان میدهند این گردشهای کاری را بهعنوان نمودارهای غیر مدور هدایتشده (DAG) تعریف کنید، برنامهریزی، نظارت و تلاش مجدد آنها را با استحکام انجام دهید.
برای ذخیرهسازی و پردازش دادهها
- اتصالدهندههای DWH ابری: کتابخانههایی مانند
snowflake-connector-python،google-cloud-bigqueryوpsycopg2(برای Redshift و PostgreSQL) امکان تعامل یکپارچه با انبارهای داده ابری اصلی را فراهم میکنند. - PyArrow: یک کتابخانه حیاتی برای کار با فرمتهای داده ستونی. این یک فرمت درون حافظه استاندارد شده ارائه میدهد و انتقال دادهها با سرعت بالا بین سیستمها را امکانپذیر میکند. این موتور پشت تعاملات کارآمد با فرمتهایی مانند Parquet است.
- کتابخانههای Lakehouse مدرن: برای راهاندازیهای پیشرفته، کتابخانههایی مانند
deltalake،py-icebergو - برای کاربران Spark - پشتیبانی بومی PySpark از این فرمتها به پایتون اجازه میدهد تا دریاچههای داده قابل اطمینان و تراکنشی بسازد که به عنوان پایه یک انبار عمل میکنند.
بخش 3: طراحی یک سیستم OLAP با پایتون
حالا بیایید از نظریه به عمل برویم. در اینجا یک راهنمای گام به گام برای طراحی سیستم تحلیلی شما آورده شده است.
مرحله 1: مدلسازی دادهها برای تجزیه و تحلیل
اساس هر سیستم OLAP خوب، مدل دادههای آن است. هدف این است که دادهها را برای پرسوجوی سریع و شهودی ساختار دهید. متداولترین و مؤثرترین مدلها، طرح ستاره و نوع آن، طرح دانه برف است.
طرح ستاره در مقابل طرح دانه برف
طرح ستاره پرکاربردترین ساختار برای انبارهای داده است. از موارد زیر تشکیل شده است:
- یک جدول واقعیت مرکزی: شامل اندازهگیریها (اعداد مورد نظر برای تجزیه و تحلیل) و کلیدهای خارجی به جداول ابعاد.
- چندین جداول ابعاد: هر جدول ابعاد به جدول واقعیت با یک کلید واحد متصل میشود و شامل ویژگیهای توصیفی است. این جداول برای سادگی و سرعت بسیار غیر نرمال هستند.
مثال: یک جدول `FactSales` با ستونهایی مانند `DateKey`، `ProductKey`، `StoreKey`، `QuantitySold` و `TotalRevenue`. این جدول توسط جداول `DimDate`، `DimProduct` و `DimStore` احاطه میشود.
طرح دانه برف توسعهای از طرح ستاره است که در آن جداول ابعاد به جداول مرتبط متعدد نرمال میشوند. به عنوان مثال، جدول `DimProduct` ممکن است به جداول `DimProduct`، `DimBrand` و `DimCategory` تجزیه شود.
توصیه: با یک طرح ستاره شروع کنید. پرسوجوها سادهتر هستند (اتصال کمتر)، و پایگاههای داده ستونی مدرن در مدیریت جداول گسترده و غیر نرمال آنقدر کارآمد هستند که مزایای ذخیرهسازی طرحهای دانه برف اغلب در مقایسه با هزینه عملکرد اضافی قابل توجه نیست.
مرحله 2: ساخت خط لوله ETL/ELT در پایتون
فرآیند ETL ستون فقراتی است که انبار داده شما را تغذیه میکند. این شامل استخراج دادهها از سیستمهای منبع، تبدیل آن به یک قالب تمیز و سازگار و بارگیری آن در مدل تحلیلی شما است.
بیایید با یک اسکریپت پایتون ساده با استفاده از Pandas، نشان دهیم. تصور کنید که ما یک فایل CSV از سفارشهای خام داریم.
# یک مثال ETL ساده شده با استفاده از پایتون و Pandas
import pandas as pd
# --- استخراج ---
print("Extracting raw order data...")
source_df = pd.read_csv('raw_orders.csv')
# --- تبدیل ---
print("Transforming data...")
# 1. دادهها را پاک کنید
source_df['order_date'] = pd.to_datetime(source_df['order_date'])
source_df['product_price'] = pd.to_numeric(source_df['product_price'], errors='coerce')
source_df.dropna(inplace=True)
# 2. دادهها را غنی کنید - یک بعد تاریخ جداگانه ایجاد کنید
dim_date = pd.DataFrame({
'DateKey': source_df['order_date'].dt.strftime('%Y%m%d').astype(int),
'Date': source_df['order_date'].dt.date,
'Year': source_df['order_date'].dt.year,
'Quarter': source_df['order_date'].dt.quarter,
'Month': source_df['order_date'].dt.month,
'DayOfWeek': source_df['order_date'].dt.day_name()
}).drop_duplicates().reset_index(drop=True)
# 3. یک بعد محصول ایجاد کنید
dim_product = source_df[['product_id', 'product_name', 'category']].copy()
dim_product.rename(columns={'product_id': 'ProductKey'}, inplace=True)
dim_product.drop_duplicates(inplace=True).reset_index(drop=True)
# 4. جدول واقعیت را ایجاد کنید
fact_sales = source_df.merge(dim_date, left_on=source_df['order_date'].dt.date, right_on='Date')\
.merge(dim_product, left_on='product_id', right_on='ProductKey')
fact_sales = fact_sales[['DateKey', 'ProductKey', 'order_id', 'quantity', 'product_price']]
fact_sales['TotalRevenue'] = fact_sales['quantity'] * fact_sales['product_price']
fact_sales.rename(columns={'order_id': 'OrderCount'}, inplace=True)
# تجمیع به گرانول مورد نظر
fact_sales = fact_sales.groupby(['DateKey', 'ProductKey']).agg(
TotalRevenue=('TotalRevenue', 'sum'),
TotalQuantity=('quantity', 'sum')
).reset_index()
# --- بارگیری ---
print("Loading data into target storage...")
# برای این مثال، ما در حال ذخیره در فایلهای Parquet هستیم، یک فرمت ستونی بسیار کارآمد
dim_date.to_parquet('warehouse/dim_date.parquet')
dim_product.to_parquet('warehouse/dim_product.parquet')
fact_sales.to_parquet('warehouse/fact_sales.parquet')
print("ETL process complete!")
این اسکریپت ساده منطق اصلی را نشان میدهد. در یک سناریوی واقعی، این منطق را در توابع قرار میدهید و اجرای آن را با یک هماهنگکننده مانند Airflow مدیریت میکنید.
مرحله 3: انتخاب و پیادهسازی موتور OLAP
با مدلسازی و بارگذاری دادههای خود، به یک موتور برای انجام عملیات OLAP نیاز دارید. در دنیای پایتون، شما چندین گزینه قدرتمند دارید، که در درجه اول از رویکرد ROLAP پیروی میکنند.
رویکرد A: نیروگاه سبک وزن - DuckDB
DuckDB یک پایگاه داده تحلیلی درون فرآیندی است که فوقالعاده سریع و آسان برای استفاده با پایتون است. میتواند مستقیماً DataFrames Pandas یا فایلهای Parquet را با استفاده از SQL پرسوجو کند. این انتخاب عالی برای سیستمهای OLAP کوچک تا متوسط، نمونههای اولیه و توسعه محلی است.
این به عنوان یک موتور ROLAP با کارایی بالا عمل میکند. شما SQL استاندارد مینویسید و DuckDB آن را با سرعت زیاد بر روی فایلهای داده شما اجرا میکند.
import duckdb
# اتصال به یک پایگاه داده درون حافظه یا یک فایل
con = duckdb.connect(database=':memory:', read_only=False)
# مستقیماً فایلهای Parquet را که قبلاً ایجاد کردهایم پرسوجو کنید
# DuckDB به طور خودکار طرحواره را درک میکند
result = con.execute("""
SELECT
p.category,
d.Year,
SUM(f.TotalRevenue) AS AnnualRevenue
FROM 'warehouse/fact_sales.parquet' AS f
JOIN 'warehouse/dim_product.parquet' AS p ON f.ProductKey = p.ProductKey
JOIN 'warehouse/dim_date.parquet' AS d ON f.DateKey = d.DateKey
WHERE p.category = 'Electronics'
GROUP BY p.category, d.Year
ORDER BY d.Year;
""").fetchdf() # fetchdf() یک DataFrame Pandas را برمیگرداند
print(result)
رویکرد B: تیتانهای در مقیاس ابر - Snowflake، BigQuery، Redshift
برای سیستمهای سازمانی در مقیاس بزرگ، یک انبار داده ابری انتخاب استاندارد است. پایتون بهطور یکپارچه با این پلتفرمها ادغام میشود. فرآیند ETL شما دادهها را در DWH ابری بارگذاری میکند، و برنامه پایتون شما (به عنوان مثال، داشبورد BI یا نوتبوک Jupyter) آن را پرسوجو میکند.
منطق مشابه DuckDB باقی میماند، اما اتصال و مقیاس متفاوت است.
import snowflake.connector
# مثال اتصال به Snowflake و اجرای یک پرسوجو
conn = snowflake.connector.connect(
user='your_user',
password='your_password',
account='your_account_identifier'
)
cursor = conn.cursor()
try:
cursor.execute("USE WAREHOUSE MY_WH;")
cursor.execute("USE DATABASE MY_DB;")
cursor.execute("""
SELECT category, YEAR(date), SUM(total_revenue)
FROM fact_sales
JOIN dim_product ON ...
JOIN dim_date ON ...
GROUP BY 1, 2;
""")
# نتایج را در صورت نیاز واکشی کنید
for row in cursor:
print(row)
finally:
cursor.close()
conn.close()
رویکرد C: متخصصان بیدرنگ - Apache Druid یا ClickHouse
برای موارد استفاده که به تأخیر پرسوجو زیر ثانیه در مجموعهدادههای عظیم و جریانی (مانند تجزیه و تحلیل بیدرنگ کاربر) نیاز دارند، پایگاههای داده تخصصی مانند Druid یا ClickHouse انتخابهای عالی هستند. آنها پایگاههای داده ستونی هستند که برای بارهای کاری OLAP طراحی شدهاند. پایتون برای انتقال دادهها به آنها و پرسوجوی آنها از طریق کتابخانههای کلاینت یا APIهای HTTP مربوطه استفاده میشود.
بخش 4: یک مثال عملی - ساخت یک سیستم OLAP کوچک
بیایید این مفاهیم را در یک مینی پروژه ترکیب کنیم: یک داشبورد فروش تعاملی. این یک سیستم OLAP مبتنی بر پایتون کامل، اگرچه ساده شده، را نشان میدهد.
پشته ما:
- ETL: پایتون و Pandas
- ذخیرهسازی دادهها: فایلهای Parquet
- موتور OLAP: DuckDB
- داشبورد: Streamlit (یک کتابخانه پایتون منبع باز برای ایجاد برنامههای وب تعاملی و زیبا برای علم داده)
ابتدا، اسکریپت ETL را از بخش 3 اجرا کنید تا فایلهای Parquet را در یک دایرکتوری `warehouse/` تولید کنید.
بعد، فایل برنامه داشبورد، `app.py` را ایجاد کنید:
# app.py - یک داشبورد فروش تعاملی ساده
import streamlit as st
import duckdb
import pandas as pd
import plotly.express as px
# --- پیکربندی صفحه ---
st.set_page_config(layout="wide", page_title="Global Sales Dashboard")
st.title("Interactive Sales OLAP Dashboard")
# --- اتصال به DuckDB ---
# این مستقیماً فایلهای Parquet ما را پرسوجو میکند
con = duckdb.connect(database=':memory:', read_only=True)
# --- بارگیری دادههای ابعاد برای فیلترها ---
@st.cache_data
def load_dimensions():
products = con.execute("SELECT DISTINCT category FROM 'warehouse/dim_product.parquet'").fetchdf()
years = con.execute("SELECT DISTINCT Year FROM 'warehouse/dim_date.parquet' ORDER BY Year").fetchdf()
return products['category'].tolist(), years['Year'].tolist()
categories, years = load_dimensions()
# --- نوار کناری برای فیلترها (برش و خرد کردن!) ---
st.sidebar.header("OLAP Filters")
selected_categories = st.sidebar.multiselect(
'Select Product Categories',
options=categories,
default=categories
)
selected_year = st.sidebar.selectbox(
'Select Year',
options=years,
index=len(years)-1 # پیشفرض برای آخرین سال
)
# --- پرسوجوی OLAP را بهصورت پویا بسازید ---
if not selected_categories:
st.warning("لطفاً حداقل یک دسته را انتخاب کنید.")
st.stop()
query = f"""
SELECT
d.Month,
d.MonthName, -- فرض بر این است که MonthName در DimDate وجود دارد
p.category,
SUM(f.TotalRevenue) AS Revenue
FROM 'warehouse/fact_sales.parquet' AS f
JOIN 'warehouse/dim_product.parquet' AS p ON f.ProductKey = p.ProductKey
JOIN 'warehouse/dim_date.parquet' AS d ON f.DateKey = d.DateKey
WHERE d.Year = {selected_year}
AND p.category IN ({str(selected_categories)[1:-1]})
GROUP BY d.Month, d.MonthName, p.category
ORDER BY d.Month;
"""
# --- اجرای پرسوجو و نمایش نتایج ---
@st.cache_data
def run_query(_query):
return con.execute(_query).fetchdf()
results_df = run_query(query)
if results_df.empty:
st.info(f"هیچ دادهای برای فیلترهای انتخابشده در سال {selected_year} یافت نشد.")
else:
# --- Visuals داشبورد اصلی ---
col1, col2 = st.columns(2)
with col1:
st.subheader(f"Monthly Revenue for {selected_year}")
fig = px.line(
results_df,
x='MonthName',
y='Revenue',
color='category',
title='Monthly Revenue by Category'
)
st.plotly_chart(fig, use_container_width=True)
with col2:
st.subheader("Revenue by Category")
category_summary = results_df.groupby('category')['Revenue'].sum().reset_index()
fig_pie = px.pie(
category_summary,
names='category',
values='Revenue',
title='Total Revenue Share by Category'
)
st.plotly_chart(fig_pie, use_container_width=True)
st.subheader("Detailed Data")
st.dataframe(results_df)
برای اجرای این، کد را بهعنوان `app.py` ذخیره کنید و `streamlit run app.py` را در ترمینال خود اجرا کنید. این یک مرورگر وب را با داشبورد تعاملی شما راهاندازی میکند. فیلترها در نوار کناری به کاربران اجازه میدهند عملیات OLAP «برش» و «خرد کردن» را انجام دهند، و داشبورد با پرسوجو مجدد DuckDB در زمان واقعی بهروزرسانی میشود.
بخش 5: مباحث پیشرفته و بهترین شیوهها
با حرکت از یک مینی پروژه به یک سیستم تولید، این موضوعات پیشرفته را در نظر بگیرید.
مقیاسپذیری و عملکرد
- از Dask برای ETL بزرگ استفاده کنید: اگر دادههای منبع شما از RAM دستگاه شما فراتر رفت، Pandas را در اسکریپتهای ETL خود با Dask جایگزین کنید. API بسیار مشابه است، اما Dask پردازش خارج از هسته و موازی را انجام میدهد.
- ذخیرهسازی ستونی کلیدی است: همیشه دادههای انبار خود را در یک فرمت ستونی مانند Apache Parquet یا ORC ذخیره کنید. این کار پرسوجوهای تحلیلی را که معمولاً فقط نیاز به خواندن چند ستون از یک جدول گسترده دارند، بهطور چشمگیری سرعت میبخشد.
- پارتیشنبندی: هنگام ذخیره دادهها در یک دریاچه داده (مانند S3 یا یک سیستم فایل محلی)، دادههای خود را بر اساس یک بعد که مرتباً فیلتر میشود، مانند تاریخ، به پوشهها تقسیم کنید. به عنوان مثال: `warehouse/fact_sales/year=2023/month=12/`. این به موتورهای پرسوجو اجازه میدهد از خواندن دادههای بیربط صرفنظر کنند، فرآیندی که به عنوان «هرس پارتیشن» شناخته میشود.
لایه معنایی
با رشد سیستم شما، متوجه خواهید شد که منطق کسبوکار (مانند تعریف «کاربر فعال» یا «حاشیه ناخالص») در چندین پرسوجو و داشبورد تکرار میشود. یک لایه معنایی با ارائه یک تعریف متمرکز و سازگار از معیارهای و ابعاد کسبوکار شما، این مشکل را حل میکند. ابزارهایی مانند dbt (ابزار ساخت داده) برای این کار استثنایی هستند. در حالی که dbt خود یک ابزار پایتون نیست، بهطور کامل در یک گردش کار هماهنگشده با پایتون ادغام میشود. شما از dbt برای مدلسازی طرح ستارهای و تعریف معیارها استفاده میکنید، و سپس میتوان از پایتون برای هماهنگی اجرای dbt و انجام تجزیه و تحلیل پیشرفته بر روی جداول تمیز حاصل استفاده کرد.
حاکمیت و کیفیت دادهها
یک انبار تنها به اندازه دادههای موجود در آن خوب است. بررسیهای کیفیت داده را مستقیماً در خطوط لوله ETL پایتون خود ادغام کنید. کتابخانههایی مانند Great Expectations به شما امکان میدهند «انتظاراتی» را در مورد دادههای خود تعریف کنید (به عنوان مثال، `customer_id` هرگز نباید تهی باشد، `revenue` باید بین 0 تا 1,000,000 باشد). سپس، اگر دادههای ورودی این قراردادها را نقض کنند، کار ETL شما میتواند شکست بخورد یا به شما هشدار دهد، و از خراب شدن دادههای بد در انبار شما جلوگیری کند.
نتیجهگیری: قدرت یک رویکرد مبتنی بر کد
پایتون اساساً چشمانداز انبار داده و هوش تجاری را تغییر داده است. این یک ابزار انعطافپذیر، قدرتمند و فروشنده-خنثی برای ساخت سیستمهای تحلیلی پیچیده از پایه ارائه میدهد. با ترکیب بهترین کتابخانههای کلاس مانند Pandas، Dask، SQLAlchemy و DuckDB، میتوانید یک سیستم OLAP کامل ایجاد کنید که هم مقیاسپذیر و هم قابل نگهداری باشد.
سفر با درک درستی از اصول مدلسازی دادهها مانند طرح ستارهای آغاز میشود. از آنجا، میتوانید خطوط لوله ETL قوی برای شکل دادن به دادههای خود بسازید، موتور پرسوجوی مناسب برای مقیاس خود را انتخاب کنید، و حتی برنامههای تحلیلی تعاملی را بسازید. این رویکرد مبتنی بر کد، که اغلب یک اصل اساسی «پشته دادههای مدرن» است، قدرت تجزیه و تحلیل را مستقیماً در دستان توسعهدهندگان و تیمهای داده قرار میدهد و آنها را قادر میسازد تا سیستمهایی را بسازند که کاملاً متناسب با نیازهای سازمانشان باشد.